from django.db import transaction
from django.db.models import Sum
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from financial_info.models import ReceiptModel, ReceiptItemModel


class ReceiptItemSerializer(serializers.ModelSerializer):
    """
        收款单中项目（销售出库单）的序列化器
    """

    # 查询当前销售出库单中已经收款到账的金额总和
    # read_only=True：只是在序列化的时候用，不是在反序列化的时候用
    # 因为加了read_only=True，不会影响新增和修改
    already_receipt = serializers.SerializerMethodField(read_only=True, help_text='已经收款到账的金额总和')

    class Meta:
        model = ReceiptItemModel
        fields = '__all__'

    def get_already_receipt(self, obj):
        """
            查询当前销售出库单中已经收款的金额
            :param obj: ReceiptItemModel
            :return: 0或者其他数值
        """
        if obj.out_storage:
            # out_storage销售出库单
            rece_dict = ReceiptItemModel.objects.filter(out_storage_id=obj.out_storage.id).exclude(
                receipt__status='0').aggregate(sum=Sum('this_money'))
            if rece_dict:
                # 如果收过款就是rece_dict['sum']，否则就是0
                return rece_dict['sum'] if rece_dict['sum'] else 0
            return 0
        return 0


class ReceiptSerializer(serializers.ModelSerializer):
    """
        新增和修改收款单的序列化和反序列化，查询列表的序列化器
    """
    # many=True表示是个列表
    # required=False：这样item_list就不是必填项了，可以省略了，适用于只付定金
    item_list = ReceiptItemSerializer(many=True, required=False)

    class Meta:
        model = ReceiptModel
        fields = '__all__'

    # 收取定金时，不需要item_list（销售出库单）。
    # 同时插入收款单和收款单中的项目（销售出库单），必须重写create
    # validated_data已经验证之后的参数
    ############################################
    # 延伸：在创建收款单时，选取销售出库单时，验证出库单是否审核，只有审核的才能选取。
    def create(self, validated_data):
        if 'item_list' not in validated_data:
            super(ReceiptSerializer, self).create(validated_data)
        item_list = validated_data.pop('item_list')
        with transaction.atomic():
            receipt = ReceiptModel.objects.create(**validated_data)
            for item in item_list:
                ReceiptItemModel.objects.create(receipt=receipt, **item)
        return receipt

    def update(self, instance, validated_data):
        # instance：就是正在修改的收款单
        if instance.status != '0':
            # 收款单的状态，0：未审核，1：已审核
            raise ValidationError('收款单已经生效，不能修改')
        # 请求参数中的新项目数据
        # item_list = validated_data.pop('item_list')
        # 如果之前有老数据（之前新增的收款单项目数据）是需要删除掉的
        # old_list = instance.item_list.all()
        with transaction.atomic():
            if 'item_list' in validated_data:
                item_list = validated_data.pop('item_list')
                old_list = instance.item_list.all()

                if old_list.exists():
                    # 然后把旧数据删除，因为在validated_data拿不到老数据的id
                    instance.item_list.all().delete()
                for item in item_list:
                    # 重新插入销售项数据
                    ReceiptItemModel.objects.create(receipt=instance, **item)

            result = super(ReceiptSerializer, self).update(instance=instance, validated_data=validated_data)
        return result

    # 收款单的状态，0：未审核，1：已审核
    # out_storage出库单的状态，0：未审核，1：已审核，2：部分收款，3：收款完成（包含欠款）
    # sale_order销售订单的状态，0：未审核，1：已审核，2：部分出库，3：全部出库，4：收取定金，5：完成销售（此订单货全部出库，全款已收）

